<script setup lang="ts">
  import { ref, onMounted, computed } from 'vue'
  import { SizeUtil, ElEvtUtil } from '@xtail/ui'
  import { AdjustableContainerPropsType } from './types'

  defineOptions({
    name: 'SAdjustableContainer'
  })

  const props = withDefaults(defineProps<AdjustableContainerPropsType>(), {
    widthAdjustable: true,
    widthDefault: '100%',
    widthMin: 0,
    widthMax: Number.MAX_SAFE_INTEGER,
    onWidthMin: () => {},
    onWidthMax: () => {},
    adjustWidthTriggerWidth: 10,
    adjustWidthTriggerPosition: 'right',
    heightAdjustable: false,
    heightDefault: '100%',
    heightMin: 0,
    heightMax: Number.MAX_SAFE_INTEGER,
    onHeightMin: () => {},
    onHeightMax: () => {},
    adjustHeightTriggerHeight: 10,
    adjustHeightTriggerPosition: 'bottom',
    placeholder: false,
    heightFollowParent: true,
    heightFollowWindow: false
  })

  const width = defineModel('width', { default: 0 })
  const height = defineModel('height', { default: 0 })

  const SAdjustableContainerRef = ref<HTMLDivElement>()

  // 宽度调整后的处理函数
  const afterWidthAdjustHandler = () => {
    if (!props.widthAdjustable) return
    width.value = Math.max(width.value, props.widthMin)
    width.value = Math.min(width.value, props.widthMax)
    if (width.value === props.widthMin) props.onWidthMin(width.value)
    else if (width.value === props.widthMax) props.onWidthMax(width.value)
  }
  // 高度调整后的处理函数
  const afterHeightAdjustHandler = () => {
    if (!props.heightAdjustable) return
    height.value = Math.max(height.value, props.heightMin)
    height.value = Math.min(height.value, props.heightMax)
    if (height.value === props.heightMin) props.onHeightMin(height.value)
    else if (height.value === props.heightMax) props.onHeightMax(height.value)
  }

  // 容器宽度和高度初始化处理
  onMounted(() => {
    if (props.widthAdjustable) {
      width.value = SAdjustableContainerRef.value?.clientWidth || props.widthMin
      afterWidthAdjustHandler()
    }
    if (props.heightAdjustable) {
      height.value = SAdjustableContainerRef.value?.clientHeight || props.heightMin
      afterHeightAdjustHandler()
    }
  })

  // 计算容器宽度
  const widthComputed = computed(() => {
    if (props.widthAdjustable) {
      return SizeUtil.unitPreHandler(width.value ? width.value : props.widthDefault)
    }
    return SizeUtil.unitPreHandler(props.widthDefault)
  })
  // 计算容器高度
  const heightComputed = computed(() => {
    if (props.heightAdjustable) {
      return SizeUtil.unitPreHandler(height.value ? height.value : props.heightDefault)
    }
    if (props.heightFollowParent) return '100%'
    if (props.heightFollowWindow) return '100vh'
    return SizeUtil.unitPreHandler(props.heightDefault)
  })
  // 计算容器 padding
  const paddingLeftComputed = computed(() => {
    if (props.placeholder && props.widthAdjustable && props.adjustWidthTriggerPosition === 'left') {
      return SizeUtil.unitPreHandler(props.adjustWidthTriggerWidth)
    }
    return 0
  })
  const paddingRightComputed = computed(() => {
    if (
      props.placeholder &&
      props.widthAdjustable &&
      props.adjustWidthTriggerPosition === 'right'
    ) {
      return SizeUtil.unitPreHandler(props.adjustWidthTriggerWidth)
    }
    return 0
  })
  const paddingTopComputed = computed(() => {
    if (
      props.placeholder &&
      props.heightAdjustable &&
      props.adjustHeightTriggerPosition === 'top'
    ) {
      return SizeUtil.unitPreHandler(props.adjustHeightTriggerHeight)
    }
    return 0
  })
  const paddingBottomComputed = computed(() => {
    if (
      props.placeholder &&
      props.heightAdjustable &&
      props.adjustHeightTriggerPosition === 'bottom'
    ) {
      return SizeUtil.unitPreHandler(props.adjustHeightTriggerHeight)
    }
    return 0
  })

  // 开始调整容器宽度
  const adjustWidthStartHandler = (evt: MouseEvent | TouchEvent) => {
    // 如果是移动端的触摸事件
    if (evt instanceof TouchEvent) {
      // 触摸开始时，触摸点位置
      const startX = evt.touches[0].pageX
      // 触摸开始时，容器宽度
      const widthOriginal = width.value
      ElEvtUtil.addTouchMoveEvtListener(document.body, (ev: TouchEvent) => {
        if (props.adjustWidthTriggerPosition === 'left')
          width.value = widthOriginal - (ev.touches[0].pageX - startX)
        else width.value = widthOriginal + (ev.touches[0].pageX - startX)
        afterWidthAdjustHandler()
      })
    }
    // 如果是 PC 端的鼠标事件
    else if (evt instanceof MouseEvent) {
      ElEvtUtil.addMouseMoveEvtListener(document.body, (ev: MouseEvent) => {
        if (props.adjustWidthTriggerPosition === 'left') width.value -= ev.movementX
        else width.value += ev.movementX
        afterWidthAdjustHandler()
      })
    }
  }
  // 开始调整容器高度
  const adjustHeightStartHandler = (evt: MouseEvent | TouchEvent) => {
    // 如果是移动端的触摸事件
    if (evt instanceof TouchEvent) {
      // 触摸开始时，触摸点位置
      const startY = evt.touches[0].pageY
      // 触摸开始时，容器高度
      const heightOriginal = height.value
      ElEvtUtil.addTouchMoveEvtListener(document.body, (ev: TouchEvent) => {
        if (props.adjustHeightTriggerPosition === 'top')
          height.value = heightOriginal - (ev.touches[0].pageY - startY)
        else height.value = heightOriginal + (ev.touches[0].pageY - startY)
        afterHeightAdjustHandler()
      })
    }
    // 如果是 PC 端的鼠标事件
    else if (evt instanceof MouseEvent) {
      ElEvtUtil.addMouseMoveEvtListener(document.body, (ev: MouseEvent) => {
        if (props.adjustHeightTriggerPosition === 'top') height.value -= ev.movementY
        else height.value += ev.movementY
        afterHeightAdjustHandler()
      })
    }
  }
</script>

<template>
  <div
    ref="SAdjustableContainerRef"
    class="s-adjustable-container"
    :style="{
      width: widthComputed,
      height: heightComputed,
      paddingLeft: paddingLeftComputed,
      paddingRight: paddingRightComputed,
      paddingTop: paddingTopComputed,
      paddingBottom: paddingBottomComputed
    }"
  >
    <slot />
    <div
      v-if="widthAdjustable"
      class="s-adjustable-container__adjust-width-trigger"
      :class="[
        adjustWidthTriggerPosition === 'left'
          ? 's-adjustable-container__adjust-width-trigger--left'
          : 's-adjustable-container__adjust-width-trigger--right'
      ]"
      :style="{ width: SizeUtil.unitPreHandler(adjustWidthTriggerWidth) }"
      @mousedown="adjustWidthStartHandler"
      @touchstart="adjustWidthStartHandler"
    ></div>
    <div
      v-if="heightAdjustable"
      class="s-adjustable-container__adjust-height-trigger"
      :class="[
        adjustHeightTriggerPosition === 'top'
          ? 's-adjustable-container__adjust-height-trigger--top'
          : 's-adjustable-container__adjust-height-trigger--bottom'
      ]"
      :style="{ height: SizeUtil.unitPreHandler(adjustHeightTriggerHeight) }"
      @mousedown="adjustHeightStartHandler"
      @touchstart="adjustHeightStartHandler"
    ></div>
  </div>
</template>

<style lang="scss">
  @use './style' as *;
</style>
